Пусть f(n) – наибольший
нечетный делитель натурального числа n.
Для заданного натурального числа n
вычислите значение суммы:
f(1) + f(2) + ... + f(n)
Вход. Каждая строка содержит одно натуральное число n (n
≤ 109).
Выход. Для каждого
значения n выведите в отдельной
строке значение суммы f(1) + f(2) + ... + f(n).
Пример
входа |
Пример
выхода |
7 1 777 |
21 1 201537 |
рекурсия
Анализ алгоритма
Если число n
нечетное, то f(n) = n.
Если число n
четное, то f(n) = f(n / 2).
Пусть
g(n) = f(1) + f(2)
+ ... + f(n)
Рассмотрим разбиение
множества натуральных чисел от 1 до n на два подмножества:
·
ODD – множество нечетных чисел,
·
EVEN – множество четных чисел.
Среди
натуральных чисел от 1 до n имеется ровно:
Тогда:
f(1) + f(3) + f(5)
+ ... + f(2k – 1) =
1 + 3 + 5 + … + (2k
– 1) =
= k2
В то же время:
f(2) + f(4) + f(6)
+ ... + f(2l) =
f(1) + f(2) + f(3)
+ ... + f(l) =
g(l) =
Для окончания
рекурсии положим g(0) = 0. Таким образом:
Пример
Рассмотрим
первый тест, в котором n = 7.
Среди
натуральных чисел от 1 до 7 имеется в точности:
·
k = = 4 нечетных числа;
·
l = = 3 четных числа.
g(7) = +
= 16 + g(3) =
16 + +
= 16 + 4 + g(1) = 16 +
4 + 1 = 21
Реализуем функцию g.
long long
g(long long n)
{
long long k = (n + 1) / 2;
if (n == 0) return 0;
return k * k
+ g(n / 2);
}
Основная часть программы. Читаем входное
значение n и выводим g(n).
while(scanf("%lld",&n)
== 1)
printf("%lld\n",g(n));
Java реализация
import java.util.*;
public class Main
{
static long g(long n)
{
long k = (n + 1) / 2;
if (n == 0) return 0;
return k * k + g(n / 2);
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
while(con.hasNext())
{
long n = con.nextLong();
System.out.println(g(n));
}
}
}
Python реализация
import sys
def g(n):
if
n == 0:
return
0
k = (n + 1) // 2
return
k * k + g(n // 2)
for line in
sys.stdin:
n = int(line)
print(g(n))